"""Initial migration with all financial data models

Revision ID: 6f13e4a7ba36
Revises: 
Create Date: 2025-06-28 09:44:43.463810

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '6f13e4a7ba36'
down_revision = None
branch_labels = None
depends_on = None


def upgrade() -> None:
    """升级数据库架构"""
    
    # 创建股票基础信息表
    op.create_table('stock_basic_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('symbol', sa.String(length=10), nullable=False, comment='股票简称'),
        sa.Column('name', sa.String(length=50), nullable=False, comment='股票名称'),
        sa.Column('area', sa.String(length=20), nullable=True, comment='地域'),
        sa.Column('industry', sa.String(length=50), nullable=True, comment='所属行业'),
        sa.Column('market', sa.String(length=10), nullable=True, comment='市场类型'),
        sa.Column('list_date', sa.Date(), nullable=True, comment='上市日期'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code'),
        comment='股票基础信息表'
    )
    op.create_index('idx_stock_basic_info_symbol', 'stock_basic_info', ['symbol'])
    op.create_index('idx_stock_basic_info_industry', 'stock_basic_info', ['industry'])
    op.create_index('idx_stock_basic_info_market', 'stock_basic_info', ['market'])
    
    # 创建股票日线数据表
    op.create_table('stock_daily_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('open', sa.Numeric(precision=10, scale=2), nullable=True, comment='开盘价'),
        sa.Column('high', sa.Numeric(precision=10, scale=2), nullable=True, comment='最高价'),
        sa.Column('low', sa.Numeric(precision=10, scale=2), nullable=True, comment='最低价'),
        sa.Column('close', sa.Numeric(precision=10, scale=2), nullable=True, comment='收盘价'),
        sa.Column('pre_close', sa.Numeric(precision=10, scale=2), nullable=True, comment='昨收价'),
        sa.Column('change', sa.Numeric(precision=10, scale=2), nullable=True, comment='涨跌额'),
        sa.Column('pct_chg', sa.Numeric(precision=8, scale=4), nullable=True, comment='涨跌幅'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='成交额'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='股票日线数据表'
    )
    op.create_index('idx_stock_daily_data_ts_code', 'stock_daily_data', ['ts_code'])
    op.create_index('idx_stock_daily_data_trade_date', 'stock_daily_data', ['trade_date'])
    op.create_index('idx_stock_daily_data_ts_code_trade_date', 'stock_daily_data', ['ts_code', 'trade_date'])
    
    # 创建股票分钟数据表
    op.create_table('stock_minute_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('trade_time', sa.DateTime(timezone=True), nullable=False, comment='交易时间'),
        sa.Column('open', sa.Numeric(precision=10, scale=2), nullable=True, comment='开盘价'),
        sa.Column('high', sa.Numeric(precision=10, scale=2), nullable=True, comment='最高价'),
        sa.Column('low', sa.Numeric(precision=10, scale=2), nullable=True, comment='最低价'),
        sa.Column('close', sa.Numeric(precision=10, scale=2), nullable=True, comment='收盘价'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='成交额'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_time'),
        comment='股票分钟数据表'
    )
    op.create_index('idx_stock_minute_data_ts_code', 'stock_minute_data', ['ts_code'])
    op.create_index('idx_stock_minute_data_trade_time', 'stock_minute_data', ['trade_time'])
    
    # 创建股票财务数据表
    op.create_table('stock_financial_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('ann_date', sa.Date(), nullable=True, comment='公告日期'),
        sa.Column('f_ann_date', sa.Date(), nullable=True, comment='实际公告日期'),
        sa.Column('end_date', sa.Date(), nullable=False, comment='报告期'),
        sa.Column('report_type', sa.String(length=10), nullable=True, comment='报告类型'),
        sa.Column('comp_type', sa.String(length=10), nullable=True, comment='公司类型'),
        sa.Column('total_revenue', sa.Numeric(precision=20, scale=2), nullable=True, comment='营业总收入'),
        sa.Column('revenue', sa.Numeric(precision=20, scale=2), nullable=True, comment='营业收入'),
        sa.Column('int_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='利息收入'),
        sa.Column('prem_earned', sa.Numeric(precision=20, scale=2), nullable=True, comment='已赚保费'),
        sa.Column('comm_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='手续费及佣金收入'),
        sa.Column('n_commis_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='手续费及佣金净收入'),
        sa.Column('n_oth_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='其他经营净收益'),
        sa.Column('n_oth_b_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='加:其他业务净收益'),
        sa.Column('prem_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='保险业务收入'),
        sa.Column('out_prem', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:分出保费'),
        sa.Column('une_prem_reser', sa.Numeric(precision=20, scale=2), nullable=True, comment='提取未到期责任准备金'),
        sa.Column('reins_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='其中:分保费收入'),
        sa.Column('n_sec_tb_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='代理买卖证券业务净收入'),
        sa.Column('n_sec_uw_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='证券承销业务净收入'),
        sa.Column('n_asset_mg_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='受托客户资产管理业务净收入'),
        sa.Column('oth_b_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='其他业务收入'),
        sa.Column('fv_value_chg_gain', sa.Numeric(precision=20, scale=2), nullable=True, comment='加:公允价值变动净收益'),
        sa.Column('invest_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='加:投资净收益'),
        sa.Column('ass_invest_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='其中:对联营企业和合营企业的投资收益'),
        sa.Column('forex_gain', sa.Numeric(precision=20, scale=2), nullable=True, comment='加:汇兑净收益'),
        sa.Column('total_cogs', sa.Numeric(precision=20, scale=2), nullable=True, comment='营业总成本'),
        sa.Column('oper_cost', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:营业成本'),
        sa.Column('int_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:利息支出'),
        sa.Column('comm_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:手续费及佣金支出'),
        sa.Column('biz_tax_surchg', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:营业税金及附加'),
        sa.Column('sell_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:销售费用'),
        sa.Column('admin_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:管理费用'),
        sa.Column('fin_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:财务费用'),
        sa.Column('assets_impair_loss', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:资产减值损失'),
        sa.Column('prem_refund', sa.Numeric(precision=20, scale=2), nullable=True, comment='退保金'),
        sa.Column('compens_payout', sa.Numeric(precision=20, scale=2), nullable=True, comment='赔付总支出'),
        sa.Column('reser_insur_liab', sa.Numeric(precision=20, scale=2), nullable=True, comment='提取保险责任准备金'),
        sa.Column('div_payt', sa.Numeric(precision=20, scale=2), nullable=True, comment='保户红利支出'),
        sa.Column('reins_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='分保费用'),
        sa.Column('oper_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='营业支出'),
        sa.Column('compens_payout_refu', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:摊回赔付支出'),
        sa.Column('insur_reser_refu', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:摊回保险责任准备金'),
        sa.Column('reins_cost_refund', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:摊回分保费用'),
        sa.Column('other_bus_cost', sa.Numeric(precision=20, scale=2), nullable=True, comment='其他业务成本'),
        sa.Column('operate_profit', sa.Numeric(precision=20, scale=2), nullable=True, comment='营业利润'),
        sa.Column('non_oper_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='加:营业外收入'),
        sa.Column('non_oper_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='减:营业外支出'),
        sa.Column('nca_disploss', sa.Numeric(precision=20, scale=2), nullable=True, comment='其中:减:非流动资产处置净损失'),
        sa.Column('total_profit', sa.Numeric(precision=20, scale=2), nullable=True, comment='利润总额'),
        sa.Column('income_tax', sa.Numeric(precision=20, scale=2), nullable=True, comment='所得税费用'),
        sa.Column('n_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='净利润(含少数股东损益)'),
        sa.Column('n_income_attr_p', sa.Numeric(precision=20, scale=2), nullable=True, comment='净利润(不含少数股东损益)'),
        sa.Column('minority_gain', sa.Numeric(precision=20, scale=2), nullable=True, comment='少数股东损益'),
        sa.Column('oth_compr_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='其他综合收益'),
        sa.Column('t_compr_income', sa.Numeric(precision=20, scale=2), nullable=True, comment='综合收益总额'),
        sa.Column('compr_inc_attr_p', sa.Numeric(precision=20, scale=2), nullable=True, comment='归属于母公司(或股东)的综合收益总额'),
        sa.Column('compr_inc_attr_m_s', sa.Numeric(precision=20, scale=2), nullable=True, comment='归属于少数股东的综合收益总额'),
        sa.Column('ebit', sa.Numeric(precision=20, scale=2), nullable=True, comment='息税前利润'),
        sa.Column('ebitda', sa.Numeric(precision=20, scale=2), nullable=True, comment='息税折旧摊销前利润'),
        sa.Column('insurance_exp', sa.Numeric(precision=20, scale=2), nullable=True, comment='保险业务支出'),
        sa.Column('undist_profit', sa.Numeric(precision=20, scale=2), nullable=True, comment='年初未分配利润'),
        sa.Column('distable_profit', sa.Numeric(precision=20, scale=2), nullable=True, comment='可分配利润'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'end_date', 'report_type'),
        comment='股票财务数据表'
    )
    op.create_index('idx_stock_financial_data_ts_code', 'stock_financial_data', ['ts_code'])
    op.create_index('idx_stock_financial_data_end_date', 'stock_financial_data', ['end_date'])
    op.create_index('idx_stock_financial_data_ann_date', 'stock_financial_data', ['ann_date'])
    
    # 创建股票技术指标表
    op.create_table('stock_technical_indicators',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('ma5', sa.Numeric(precision=10, scale=2), nullable=True, comment='5日均线'),
        sa.Column('ma10', sa.Numeric(precision=10, scale=2), nullable=True, comment='10日均线'),
        sa.Column('ma20', sa.Numeric(precision=10, scale=2), nullable=True, comment='20日均线'),
        sa.Column('ma60', sa.Numeric(precision=10, scale=2), nullable=True, comment='60日均线'),
        sa.Column('rsi', sa.Numeric(precision=8, scale=4), nullable=True, comment='相对强弱指标'),
        sa.Column('macd', sa.Numeric(precision=10, scale=6), nullable=True, comment='MACD'),
        sa.Column('kdj_k', sa.Numeric(precision=8, scale=4), nullable=True, comment='KDJ指标K值'),
        sa.Column('kdj_d', sa.Numeric(precision=8, scale=4), nullable=True, comment='KDJ指标D值'),
        sa.Column('kdj_j', sa.Numeric(precision=8, scale=4), nullable=True, comment='KDJ指标J值'),
        sa.Column('boll_upper', sa.Numeric(precision=10, scale=2), nullable=True, comment='布林带上轨'),
        sa.Column('boll_mid', sa.Numeric(precision=10, scale=2), nullable=True, comment='布林带中轨'),
        sa.Column('boll_lower', sa.Numeric(precision=10, scale=2), nullable=True, comment='布林带下轨'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='股票技术指标表'
    )
    op.create_index('idx_stock_technical_indicators_ts_code', 'stock_technical_indicators', ['ts_code'])
    op.create_index('idx_stock_technical_indicators_trade_date', 'stock_technical_indicators', ['trade_date'])
    
    # 创建股票资金流向表
    op.create_table('stock_money_flow',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('buy_sm_vol', sa.BigInteger(), nullable=True, comment='小单买入量'),
        sa.Column('buy_sm_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='小单买入金额'),
        sa.Column('sell_sm_vol', sa.BigInteger(), nullable=True, comment='小单卖出量'),
        sa.Column('sell_sm_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='小单卖出金额'),
        sa.Column('buy_md_vol', sa.BigInteger(), nullable=True, comment='中单买入量'),
        sa.Column('buy_md_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='中单买入金额'),
        sa.Column('sell_md_vol', sa.BigInteger(), nullable=True, comment='中单卖出量'),
        sa.Column('sell_md_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='中单卖出金额'),
        sa.Column('buy_lg_vol', sa.BigInteger(), nullable=True, comment='大单买入量'),
        sa.Column('buy_lg_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='大单买入金额'),
        sa.Column('sell_lg_vol', sa.BigInteger(), nullable=True, comment='大单卖出量'),
        sa.Column('sell_lg_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='大单卖出金额'),
        sa.Column('buy_elg_vol', sa.BigInteger(), nullable=True, comment='特大单买入量'),
        sa.Column('buy_elg_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='特大单买入金额'),
        sa.Column('sell_elg_vol', sa.BigInteger(), nullable=True, comment='特大单卖出量'),
        sa.Column('sell_elg_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='特大单卖出金额'),
        sa.Column('net_mf_vol', sa.BigInteger(), nullable=True, comment='净流入量'),
        sa.Column('net_mf_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='净流入额'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='股票资金流向表'
    )
    op.create_index('idx_stock_money_flow_ts_code', 'stock_money_flow', ['ts_code'])
    op.create_index('idx_stock_money_flow_trade_date', 'stock_money_flow', ['trade_date'])
    
    # 创建股票股东信息表
    op.create_table('stock_holder_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('ann_date', sa.Date(), nullable=True, comment='公告日期'),
        sa.Column('end_date', sa.Date(), nullable=False, comment='报告期'),
        sa.Column('holder_name', sa.String(length=100), nullable=False, comment='股东名称'),
        sa.Column('hold_amount', sa.BigInteger(), nullable=True, comment='持有数量'),
        sa.Column('hold_ratio', sa.Numeric(precision=8, scale=4), nullable=True, comment='持股比例'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'end_date', 'holder_name'),
        comment='股票股东信息表'
    )
    op.create_index('idx_stock_holder_info_ts_code', 'stock_holder_info', ['ts_code'])
    op.create_index('idx_stock_holder_info_end_date', 'stock_holder_info', ['end_date'])
    op.create_index('idx_stock_holder_info_holder_name', 'stock_holder_info', ['holder_name'])
    
    # 创建股票分红送股表
    op.create_table('stock_dividend_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('div_proc', sa.String(length=20), nullable=True, comment='实施进度'),
        sa.Column('stk_div', sa.Numeric(precision=8, scale=4), nullable=True, comment='每股送转'),
        sa.Column('stk_bo_rate', sa.Numeric(precision=8, scale=4), nullable=True, comment='每股送股比例'),
        sa.Column('stk_co_rate', sa.Numeric(precision=8, scale=4), nullable=True, comment='每股转增比例'),
        sa.Column('cash_div', sa.Numeric(precision=8, scale=4), nullable=True, comment='每股分红'),
        sa.Column('cash_div_tax', sa.Numeric(precision=8, scale=4), nullable=True, comment='扣税后每股分红'),
        sa.Column('record_date', sa.Date(), nullable=True, comment='股权登记日'),
        sa.Column('ex_date', sa.Date(), nullable=True, comment='除权除息日'),
        sa.Column('pay_date', sa.Date(), nullable=True, comment='派息日'),
        sa.Column('div_listdate', sa.Date(), nullable=True, comment='红股上市日'),
        sa.Column('imp_ann_date', sa.Date(), nullable=True, comment='实施公告日'),
        sa.Column('base_date', sa.Date(), nullable=True, comment='基准日'),
        sa.Column('base_share', sa.BigInteger(), nullable=True, comment='基准股本'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        comment='股票分红送股表'
    )
    op.create_index('idx_stock_dividend_info_ts_code', 'stock_dividend_info', ['ts_code'])
    op.create_index('idx_stock_dividend_info_record_date', 'stock_dividend_info', ['record_date'])
    op.create_index('idx_stock_dividend_info_ex_date', 'stock_dividend_info', ['ex_date'])
    
    # 创建债券基础信息表
    op.create_table('bond_basic_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='债券代码'),
        sa.Column('bond_short_name', sa.String(length=50), nullable=False, comment='债券简称'),
        sa.Column('bond_full_name', sa.String(length=100), nullable=True, comment='债券全称'),
        sa.Column('bond_type', sa.String(length=20), nullable=True, comment='债券类型'),
        sa.Column('market', sa.String(length=10), nullable=True, comment='上市市场'),
        sa.Column('list_date', sa.Date(), nullable=True, comment='上市日期'),
        sa.Column('delist_date', sa.Date(), nullable=True, comment='摘牌日期'),
        sa.Column('issue_date', sa.Date(), nullable=True, comment='发行起始日'),
        sa.Column('mat_date', sa.Date(), nullable=True, comment='到期日期'),
        sa.Column('par_value', sa.Numeric(precision=10, scale=2), nullable=True, comment='票面价值'),
        sa.Column('issue_price', sa.Numeric(precision=10, scale=2), nullable=True, comment='发行价格'),
        sa.Column('issue_size', sa.Numeric(precision=15, scale=2), nullable=True, comment='发行总额'),
        sa.Column('coupon_rate', sa.Numeric(precision=8, scale=4), nullable=True, comment='票面利率'),
        sa.Column('pay_per_year', sa.Integer(), nullable=True, comment='每年付息次数'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code'),
        comment='债券基础信息表'
    )
    op.create_index('idx_bond_basic_info_bond_type', 'bond_basic_info', ['bond_type'])
    op.create_index('idx_bond_basic_info_market', 'bond_basic_info', ['market'])
    op.create_index('idx_bond_basic_info_mat_date', 'bond_basic_info', ['mat_date'])
    
    # 创建债券日线数据表
    op.create_table('bond_daily_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='债券代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('open', sa.Numeric(precision=10, scale=2), nullable=True, comment='开盘价'),
        sa.Column('high', sa.Numeric(precision=10, scale=2), nullable=True, comment='最高价'),
        sa.Column('low', sa.Numeric(precision=10, scale=2), nullable=True, comment='最低价'),
        sa.Column('close', sa.Numeric(precision=10, scale=2), nullable=True, comment='收盘价'),
        sa.Column('pre_close', sa.Numeric(precision=10, scale=2), nullable=True, comment='昨收价'),
        sa.Column('change', sa.Numeric(precision=10, scale=2), nullable=True, comment='涨跌额'),
        sa.Column('pct_chg', sa.Numeric(precision=8, scale=4), nullable=True, comment='涨跌幅'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='成交额'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='债券日线数据表'
    )
    op.create_index('idx_bond_daily_data_ts_code', 'bond_daily_data', ['ts_code'])
    op.create_index('idx_bond_daily_data_trade_date', 'bond_daily_data', ['trade_date'])
    
    # 创建债券收益率数据表
    op.create_table('bond_yield_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='债券代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('yield_to_maturity', sa.Numeric(precision=8, scale=4), nullable=True, comment='到期收益率'),
        sa.Column('modified_duration', sa.Numeric(precision=8, scale=4), nullable=True, comment='修正久期'),
        sa.Column('convexity', sa.Numeric(precision=8, scale=4), nullable=True, comment='凸性'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='债券收益率数据表'
    )
    op.create_index('idx_bond_yield_data_ts_code', 'bond_yield_data', ['ts_code'])
    op.create_index('idx_bond_yield_data_trade_date', 'bond_yield_data', ['trade_date'])
    
    # 创建债券评级数据表
    op.create_table('bond_rating_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='债券代码'),
        sa.Column('rating_agency', sa.String(length=50), nullable=False, comment='评级机构'),
        sa.Column('rating', sa.String(length=10), nullable=True, comment='信用评级'),
        sa.Column('rating_date', sa.Date(), nullable=False, comment='评级日期'),
        sa.Column('outlook', sa.String(length=20), nullable=True, comment='评级展望'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'rating_agency', 'rating_date'),
        comment='债券评级数据表'
    )
    op.create_index('idx_bond_rating_data_ts_code', 'bond_rating_data', ['ts_code'])
    op.create_index('idx_bond_rating_data_rating_agency', 'bond_rating_data', ['rating_agency'])
    op.create_index('idx_bond_rating_data_rating_date', 'bond_rating_data', ['rating_date'])
    
    # 创建债券发行人信息表
    op.create_table('bond_issuer_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='债券代码'),
        sa.Column('issuer_name', sa.String(length=100), nullable=False, comment='发行人名称'),
        sa.Column('issuer_type', sa.String(length=20), nullable=True, comment='发行人类型'),
        sa.Column('industry', sa.String(length=50), nullable=True, comment='所属行业'),
        sa.Column('province', sa.String(length=20), nullable=True, comment='所在省份'),
        sa.Column('city', sa.String(length=20), nullable=True, comment='所在城市'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code'),
        comment='债券发行人信息表'
    )
    op.create_index('idx_bond_issuer_info_issuer_name', 'bond_issuer_info', ['issuer_name'])
    op.create_index('idx_bond_issuer_info_issuer_type', 'bond_issuer_info', ['issuer_type'])
    op.create_index('idx_bond_issuer_info_industry', 'bond_issuer_info', ['industry'])
    
    # 创建基金基础信息表
    op.create_table('fund_basic_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='基金代码'),
        sa.Column('name', sa.String(length=50), nullable=False, comment='基金简称'),
        sa.Column('management', sa.String(length=50), nullable=True, comment='管理人'),
        sa.Column('custodian', sa.String(length=50), nullable=True, comment='托管人'),
        sa.Column('fund_type', sa.String(length=20), nullable=True, comment='基金类型'),
        sa.Column('found_date', sa.Date(), nullable=True, comment='成立日期'),
        sa.Column('due_date', sa.Date(), nullable=True, comment='到期日期'),
        sa.Column('list_date', sa.Date(), nullable=True, comment='上市时间'),
        sa.Column('issue_date', sa.Date(), nullable=True, comment='发行日期'),
        sa.Column('delist_date', sa.Date(), nullable=True, comment='退市日期'),
        sa.Column('issue_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='发行份额'),
        sa.Column('m_fee', sa.Numeric(precision=8, scale=4), nullable=True, comment='管理费'),
        sa.Column('c_fee', sa.Numeric(precision=8, scale=4), nullable=True, comment='托管费'),
        sa.Column('duration_year', sa.Numeric(precision=8, scale=4), nullable=True, comment='存续期'),
        sa.Column('p_value', sa.Numeric(precision=10, scale=2), nullable=True, comment='面值'),
        sa.Column('min_amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='起点金额'),
        sa.Column('exp_return', sa.Numeric(precision=8, scale=4), nullable=True, comment='预期收益率'),
        sa.Column('benchmark', sa.String(length=200), nullable=True, comment='业绩比较基准'),
        sa.Column('status', sa.String(length=10), nullable=True, comment='存续状态'),
        sa.Column('invest_type', sa.String(length=20), nullable=True, comment='投资类型'),
        sa.Column('type', sa.String(length=20), nullable=True, comment='基金类型'),
        sa.Column('trustee', sa.String(length=50), nullable=True, comment='受托人'),
        sa.Column('purc_startdate', sa.Date(), nullable=True, comment='日常申购起始日'),
        sa.Column('redm_startdate', sa.Date(), nullable=True, comment='日常赎回起始日'),
        sa.Column('market', sa.String(length=10), nullable=True, comment='上市地点'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code'),
        comment='基金基础信息表'
    )
    op.create_index('idx_fund_basic_info_name', 'fund_basic_info', ['name'])
    op.create_index('idx_fund_basic_info_management', 'fund_basic_info', ['management'])
    op.create_index('idx_fund_basic_info_fund_type', 'fund_basic_info', ['fund_type'])
    op.create_index('idx_fund_basic_info_status', 'fund_basic_info', ['status'])
    
    # 创建基金净值数据表
    op.create_table('fund_nav_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='基金代码'),
        sa.Column('ann_date', sa.Date(), nullable=True, comment='公告日期'),
        sa.Column('nav_date', sa.Date(), nullable=False, comment='净值日期'),
        sa.Column('unit_nav', sa.Numeric(precision=10, scale=4), nullable=True, comment='单位净值'),
        sa.Column('accum_nav', sa.Numeric(precision=10, scale=4), nullable=True, comment='累计净值'),
        sa.Column('accum_div', sa.Numeric(precision=10, scale=4), nullable=True, comment='累计分红'),
        sa.Column('net_asset', sa.Numeric(precision=15, scale=2), nullable=True, comment='资产净值'),
        sa.Column('total_netasset', sa.Numeric(precision=15, scale=2), nullable=True, comment='合计资产净值'),
        sa.Column('adj_nav', sa.Numeric(precision=10, scale=4), nullable=True, comment='复权单位净值'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'nav_date'),
        comment='基金净值数据表'
    )
    op.create_index('idx_fund_nav_data_ts_code', 'fund_nav_data', ['ts_code'])
    op.create_index('idx_fund_nav_data_nav_date', 'fund_nav_data', ['nav_date'])
    
    # 创建基金持仓数据表
    op.create_table('fund_portfolio_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='基金代码'),
        sa.Column('ann_date', sa.Date(), nullable=True, comment='公告日期'),
        sa.Column('end_date', sa.Date(), nullable=False, comment='报告期'),
        sa.Column('symbol', sa.String(length=20), nullable=False, comment='股票代码'),
        sa.Column('mkv', sa.Numeric(precision=15, scale=2), nullable=True, comment='持有股票市值'),
        sa.Column('amount', sa.BigInteger(), nullable=True, comment='持有股票数量'),
        sa.Column('stk_mkv_ratio', sa.Numeric(precision=8, scale=4), nullable=True, comment='占股票市值比'),
        sa.Column('stk_float_ratio', sa.Numeric(precision=8, scale=4), nullable=True, comment='占流通股本比例'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'end_date', 'symbol'),
        comment='基金持仓数据表'
    )
    op.create_index('idx_fund_portfolio_data_ts_code', 'fund_portfolio_data', ['ts_code'])
    op.create_index('idx_fund_portfolio_data_end_date', 'fund_portfolio_data', ['end_date'])
    op.create_index('idx_fund_portfolio_data_symbol', 'fund_portfolio_data', ['symbol'])
    
    # 创建基金经理信息表
    op.create_table('fund_manager_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='基金代码'),
        sa.Column('ann_date', sa.Date(), nullable=True, comment='公告日期'),
        sa.Column('name', sa.String(length=50), nullable=False, comment='姓名'),
        sa.Column('offset', sa.Date(), nullable=True, comment='离任日期'),
        sa.Column('terminate_date', sa.Date(), nullable=True, comment='离任日期'),
        sa.Column('resume', sa.Text(), nullable=True, comment='简历'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        comment='基金经理信息表'
    )
    op.create_index('idx_fund_manager_info_ts_code', 'fund_manager_info', ['ts_code'])
    op.create_index('idx_fund_manager_info_name', 'fund_manager_info', ['name'])
    
    # 创建基金分红数据表
    op.create_table('fund_dividend_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='基金代码'),
        sa.Column('ann_date', sa.Date(), nullable=True, comment='公告日期'),
        sa.Column('imp_anndate', sa.Date(), nullable=True, comment='分红实施公告日'),
        sa.Column('base_date', sa.Date(), nullable=True, comment='基准日期'),
        sa.Column('div_proc', sa.String(length=20), nullable=True, comment='方案进度'),
        sa.Column('record_date', sa.Date(), nullable=True, comment='权益登记日'),
        sa.Column('ex_date', sa.Date(), nullable=True, comment='除息日'),
        sa.Column('pay_date', sa.Date(), nullable=True, comment='红利发放日'),
        sa.Column('div_cash', sa.Numeric(precision=10, scale=4), nullable=True, comment='每10份派现金'),
        sa.Column('div_rate', sa.Numeric(precision=8, scale=4), nullable=True, comment='分红比例'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        comment='基金分红数据表'
    )
    op.create_index('idx_fund_dividend_data_ts_code', 'fund_dividend_data', ['ts_code'])
    op.create_index('idx_fund_dividend_data_record_date', 'fund_dividend_data', ['record_date'])
    op.create_index('idx_fund_dividend_data_ex_date', 'fund_dividend_data', ['ex_date'])
    
    # 创建基金规模数据表
    op.create_table('fund_share_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='基金代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('fd_share', sa.Numeric(precision=15, scale=2), nullable=True, comment='基金份额'),
        sa.Column('netasset', sa.Numeric(precision=15, scale=2), nullable=True, comment='资产净值'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='基金规模数据表'
    )
    op.create_index('idx_fund_share_data_ts_code', 'fund_share_data', ['ts_code'])
    op.create_index('idx_fund_share_data_trade_date', 'fund_share_data', ['trade_date'])
    
    # 创建期货基础信息表
    op.create_table('futures_basic_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期货代码'),
        sa.Column('symbol', sa.String(length=20), nullable=False, comment='交易标识'),
        sa.Column('exchange', sa.String(length=10), nullable=False, comment='交易所代码'),
        sa.Column('name', sa.String(length=50), nullable=False, comment='中文简称'),
        sa.Column('fut_code', sa.String(length=20), nullable=True, comment='合约产品代码'),
        sa.Column('multiplier', sa.Numeric(precision=10, scale=2), nullable=True, comment='合约乘数'),
        sa.Column('trade_unit', sa.String(length=20), nullable=True, comment='交易单位'),
        sa.Column('per_unit', sa.Numeric(precision=10, scale=2), nullable=True, comment='交易单位每手'),
        sa.Column('quote_unit', sa.String(length=20), nullable=True, comment='报价单位'),
        sa.Column('quote_unit_desc', sa.String(length=50), nullable=True, comment='最小报价单位说明'),
        sa.Column('d_mode_desc', sa.String(length=100), nullable=True, comment='交割方式说明'),
        sa.Column('list_date', sa.Date(), nullable=True, comment='上市日期'),
        sa.Column('delist_date', sa.Date(), nullable=True, comment='最后交易日期'),
        sa.Column('d_month', sa.String(length=20), nullable=True, comment='交割月份'),
        sa.Column('last_ddate', sa.Date(), nullable=True, comment='最后交割日'),
        sa.Column('trade_time_desc', sa.String(length=100), nullable=True, comment='交易时间说明'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code'),
        comment='期货基础信息表'
    )
    op.create_index('idx_futures_basic_info_symbol', 'futures_basic_info', ['symbol'])
    op.create_index('idx_futures_basic_info_exchange', 'futures_basic_info', ['exchange'])
    op.create_index('idx_futures_basic_info_fut_code', 'futures_basic_info', ['fut_code'])
    
    # 创建期货日线数据表
    op.create_table('futures_daily_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期货代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('open', sa.Numeric(precision=12, scale=2), nullable=True, comment='开盘价'),
        sa.Column('high', sa.Numeric(precision=12, scale=2), nullable=True, comment='最高价'),
        sa.Column('low', sa.Numeric(precision=12, scale=2), nullable=True, comment='最低价'),
        sa.Column('close', sa.Numeric(precision=12, scale=2), nullable=True, comment='收盘价'),
        sa.Column('pre_close', sa.Numeric(precision=12, scale=2), nullable=True, comment='昨收价'),
        sa.Column('change', sa.Numeric(precision=12, scale=2), nullable=True, comment='涨跌额'),
        sa.Column('pct_chg', sa.Numeric(precision=8, scale=4), nullable=True, comment='涨跌幅'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=18, scale=2), nullable=True, comment='成交额'),
        sa.Column('oi', sa.BigInteger(), nullable=True, comment='持仓量'),
        sa.Column('oi_chg', sa.BigInteger(), nullable=True, comment='持仓量变化'),
        sa.Column('settle', sa.Numeric(precision=12, scale=2), nullable=True, comment='结算价'),
        sa.Column('pre_settle', sa.Numeric(precision=12, scale=2), nullable=True, comment='前结算价'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='期货日线数据表'
    )
    op.create_index('idx_futures_daily_data_ts_code', 'futures_daily_data', ['ts_code'])
    op.create_index('idx_futures_daily_data_trade_date', 'futures_daily_data', ['trade_date'])
    
    # 创建期货持仓数据表
    op.create_table('futures_holding_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('symbol', sa.String(length=20), nullable=False, comment='合约代码'),
        sa.Column('broker', sa.String(length=50), nullable=False, comment='期货公司会员简称'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='成交量'),
        sa.Column('vol_chg', sa.BigInteger(), nullable=True, comment='成交量变化'),
        sa.Column('long_hld', sa.BigInteger(), nullable=True, comment='持买仓量'),
        sa.Column('long_chg', sa.BigInteger(), nullable=True, comment='持买仓变化'),
        sa.Column('short_hld', sa.BigInteger(), nullable=True, comment='持卖仓量'),
        sa.Column('short_chg', sa.BigInteger(), nullable=True, comment='持卖仓变化'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('symbol', 'broker', 'trade_date'),
        comment='期货持仓数据表'
    )
    op.create_index('idx_futures_holding_data_symbol', 'futures_holding_data', ['symbol'])
    op.create_index('idx_futures_holding_data_broker', 'futures_holding_data', ['broker'])
    op.create_index('idx_futures_holding_data_trade_date', 'futures_holding_data', ['trade_date'])
    
    # 创建期货仓单数据表
    op.create_table('futures_warehouse_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('symbol', sa.String(length=20), nullable=False, comment='品种代码'),
        sa.Column('warehouse', sa.String(length=50), nullable=False, comment='仓库名称'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='仓单数量'),
        sa.Column('vol_chg', sa.BigInteger(), nullable=True, comment='仓单日增减'),
        sa.Column('area', sa.String(length=20), nullable=True, comment='地区'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='日期'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('symbol', 'warehouse', 'trade_date'),
        comment='期货仓单数据表'
    )
    op.create_index('idx_futures_warehouse_data_symbol', 'futures_warehouse_data', ['symbol'])
    op.create_index('idx_futures_warehouse_data_warehouse', 'futures_warehouse_data', ['warehouse'])
    op.create_index('idx_futures_warehouse_data_trade_date', 'futures_warehouse_data', ['trade_date'])
    
    # 创建期货主力合约表
    op.create_table('futures_main_contract',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期货代码'),
        sa.Column('symbol', sa.String(length=20), nullable=False, comment='交易标识'),
        sa.Column('exchange', sa.String(length=10), nullable=False, comment='交易所'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('is_main', sa.Boolean(), nullable=False, comment='是否主力合约'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='期货主力合约表'
    )
    op.create_index('idx_futures_main_contract_symbol', 'futures_main_contract', ['symbol'])
    op.create_index('idx_futures_main_contract_exchange', 'futures_main_contract', ['exchange'])
    op.create_index('idx_futures_main_contract_trade_date', 'futures_main_contract', ['trade_date'])
    op.create_index('idx_futures_main_contract_is_main', 'futures_main_contract', ['is_main'])
    
    # 创建期货分钟数据表
    op.create_table('futures_minute_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期货代码'),
        sa.Column('trade_time', sa.DateTime(timezone=True), nullable=False, comment='交易时间'),
        sa.Column('open', sa.Numeric(precision=12, scale=2), nullable=True, comment='开盘价'),
        sa.Column('high', sa.Numeric(precision=12, scale=2), nullable=True, comment='最高价'),
        sa.Column('low', sa.Numeric(precision=12, scale=2), nullable=True, comment='最低价'),
        sa.Column('close', sa.Numeric(precision=12, scale=2), nullable=True, comment='收盘价'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=18, scale=2), nullable=True, comment='成交额'),
        sa.Column('oi', sa.BigInteger(), nullable=True, comment='持仓量'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_time'),
        comment='期货分钟数据表'
    )
    op.create_index('idx_futures_minute_data_ts_code', 'futures_minute_data', ['ts_code'])
    op.create_index('idx_futures_minute_data_trade_time', 'futures_minute_data', ['trade_time'])
    
    # 创建期权基础信息表
    op.create_table('options_basic_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期权代码'),
        sa.Column('exchange', sa.String(length=10), nullable=False, comment='交易所'),
        sa.Column('name', sa.String(length=50), nullable=False, comment='期权名称'),
        sa.Column('per_unit', sa.String(length=20), nullable=True, comment='合约单位'),
        sa.Column('opt_code', sa.String(length=20), nullable=True, comment='标准合约代码'),
        sa.Column('opt_type', sa.String(length=10), nullable=True, comment='期权类型'),
        sa.Column('call_put', sa.String(length=10), nullable=True, comment='期权方向'),
        sa.Column('exercise_type', sa.String(length=10), nullable=True, comment='行权方式'),
        sa.Column('exercise_price', sa.Numeric(precision=10, scale=2), nullable=True, comment='行权价格'),
        sa.Column('s_month', sa.String(length=10), nullable=True, comment='结算月'),
        sa.Column('maturity_date', sa.Date(), nullable=True, comment='到期日'),
        sa.Column('list_price', sa.Numeric(precision=10, scale=2), nullable=True, comment='挂牌基准价'),
        sa.Column('list_date', sa.Date(), nullable=True, comment='开始交易日期'),
        sa.Column('delist_date', sa.Date(), nullable=True, comment='最后交易日期'),
        sa.Column('last_edate', sa.Date(), nullable=True, comment='最后行权日期'),
        sa.Column('last_ddate', sa.Date(), nullable=True, comment='最后交割日期'),
        sa.Column('quote_unit', sa.String(length=20), nullable=True, comment='报价单位'),
        sa.Column('min_price_chg', sa.Numeric(precision=10, scale=4), nullable=True, comment='最小价格波动'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code'),
        comment='期权基础信息表'
    )
    op.create_index('idx_options_basic_info_exchange', 'options_basic_info', ['exchange'])
    op.create_index('idx_options_basic_info_opt_type', 'options_basic_info', ['opt_type'])
    op.create_index('idx_options_basic_info_call_put', 'options_basic_info', ['call_put'])
    op.create_index('idx_options_basic_info_maturity_date', 'options_basic_info', ['maturity_date'])
    
    # 创建期权日线数据表
    op.create_table('options_daily_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期权代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('exchange', sa.String(length=10), nullable=False, comment='交易所'),
        sa.Column('pre_settle', sa.Numeric(precision=10, scale=4), nullable=True, comment='昨结算价'),
        sa.Column('pre_close', sa.Numeric(precision=10, scale=4), nullable=True, comment='前收盘价'),
        sa.Column('open', sa.Numeric(precision=10, scale=4), nullable=True, comment='开盘价'),
        sa.Column('high', sa.Numeric(precision=10, scale=4), nullable=True, comment='最高价'),
        sa.Column('low', sa.Numeric(precision=10, scale=4), nullable=True, comment='最低价'),
        sa.Column('close', sa.Numeric(precision=10, scale=4), nullable=True, comment='收盘价'),
        sa.Column('settle', sa.Numeric(precision=10, scale=4), nullable=True, comment='结算价'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='成交额'),
        sa.Column('oi', sa.BigInteger(), nullable=True, comment='持仓量'),
        sa.Column('oi_chg', sa.BigInteger(), nullable=True, comment='持仓量变化'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='期权日线数据表'
    )
    op.create_index('idx_options_daily_data_ts_code', 'options_daily_data', ['ts_code'])
    op.create_index('idx_options_daily_data_trade_date', 'options_daily_data', ['trade_date'])
    op.create_index('idx_options_daily_data_exchange', 'options_daily_data', ['exchange'])
    
    # 创建期权希腊字母数据表
    op.create_table('options_greeks_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期权代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('delta', sa.Numeric(precision=10, scale=6), nullable=True, comment='Delta值'),
        sa.Column('gamma', sa.Numeric(precision=10, scale=6), nullable=True, comment='Gamma值'),
        sa.Column('theta', sa.Numeric(precision=10, scale=6), nullable=True, comment='Theta值'),
        sa.Column('vega', sa.Numeric(precision=10, scale=6), nullable=True, comment='Vega值'),
        sa.Column('rho', sa.Numeric(precision=10, scale=6), nullable=True, comment='Rho值'),
        sa.Column('implied_volatility', sa.Numeric(precision=8, scale=4), nullable=True, comment='隐含波动率'),
        sa.Column('time_value', sa.Numeric(precision=10, scale=4), nullable=True, comment='时间价值'),
        sa.Column('intrinsic_value', sa.Numeric(precision=10, scale=4), nullable=True, comment='内在价值'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='期权希腊字母数据表'
    )
    op.create_index('idx_options_greeks_data_ts_code', 'options_greeks_data', ['ts_code'])
    op.create_index('idx_options_greeks_data_trade_date', 'options_greeks_data', ['trade_date'])
    
    # 创建期权持仓分析表
    op.create_table('options_position_analysis',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期权代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('exchange', sa.String(length=10), nullable=False, comment='交易所'),
        sa.Column('oi_total', sa.BigInteger(), nullable=True, comment='总持仓量'),
        sa.Column('oi_chg', sa.BigInteger(), nullable=True, comment='持仓量变化'),
        sa.Column('vol_ratio', sa.Numeric(precision=8, scale=4), nullable=True, comment='成交量比率'),
        sa.Column('pcr', sa.Numeric(precision=8, scale=4), nullable=True, comment='认沽认购比'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='期权持仓分析表'
    )
    op.create_index('idx_options_position_analysis_ts_code', 'options_position_analysis', ['ts_code'])
    op.create_index('idx_options_position_analysis_trade_date', 'options_position_analysis', ['trade_date'])
    op.create_index('idx_options_position_analysis_exchange', 'options_position_analysis', ['exchange'])
    
    # 创建期权分钟数据表
    op.create_table('options_minute_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='期权代码'),
        sa.Column('trade_time', sa.DateTime(timezone=True), nullable=False, comment='交易时间'),
        sa.Column('open', sa.Numeric(precision=10, scale=4), nullable=True, comment='开盘价'),
        sa.Column('high', sa.Numeric(precision=10, scale=4), nullable=True, comment='最高价'),
        sa.Column('low', sa.Numeric(precision=10, scale=4), nullable=True, comment='最低价'),
        sa.Column('close', sa.Numeric(precision=10, scale=4), nullable=True, comment='收盘价'),
        sa.Column('vol', sa.BigInteger(), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=15, scale=2), nullable=True, comment='成交额'),
        sa.Column('oi', sa.BigInteger(), nullable=True, comment='持仓量'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_time'),
        comment='期权分钟数据表'
    )
    op.create_index('idx_options_minute_data_ts_code', 'options_minute_data', ['ts_code'])
    op.create_index('idx_options_minute_data_trade_time', 'options_minute_data', ['trade_time'])
    
    # 创建宏观经济数据表
    op.create_table('macro_economic_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('indicator_code', sa.String(length=20), nullable=False, comment='指标代码'),
        sa.Column('indicator_name', sa.String(length=100), nullable=False, comment='指标名称'),
        sa.Column('period', sa.String(length=10), nullable=False, comment='数据周期'),
        sa.Column('period_date', sa.Date(), nullable=False, comment='数据日期'),
        sa.Column('value', sa.Numeric(precision=20, scale=4), nullable=True, comment='指标值'),
        sa.Column('unit', sa.String(length=20), nullable=True, comment='单位'),
        sa.Column('source', sa.String(length=50), nullable=True, comment='数据来源'),
        sa.Column('publish_date', sa.Date(), nullable=True, comment='发布日期'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('indicator_code', 'period_date'),
        comment='宏观经济数据表'
    )
    op.create_index('idx_macro_economic_data_indicator_code', 'macro_economic_data', ['indicator_code'])
    op.create_index('idx_macro_economic_data_period_date', 'macro_economic_data', ['period_date'])
    op.create_index('idx_macro_economic_data_publish_date', 'macro_economic_data', ['publish_date'])
    
    # 创建GDP数据表
    op.create_table('gdp_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('quarter', sa.String(length=10), nullable=False, comment='季度'),
        sa.Column('gdp', sa.Numeric(precision=20, scale=2), nullable=True, comment='国内生产总值'),
        sa.Column('gdp_yoy', sa.Numeric(precision=8, scale=4), nullable=True, comment='GDP同比增长率'),
        sa.Column('gdp_qoq', sa.Numeric(precision=8, scale=4), nullable=True, comment='GDP环比增长率'),
        sa.Column('pi', sa.Numeric(precision=20, scale=2), nullable=True, comment='第一产业'),
        sa.Column('si', sa.Numeric(precision=20, scale=2), nullable=True, comment='第二产业'),
        sa.Column('ti', sa.Numeric(precision=20, scale=2), nullable=True, comment='第三产业'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('quarter'),
        comment='GDP数据表'
    )
    op.create_index('idx_gdp_data_quarter', 'gdp_data', ['quarter'])
    
    # 创建CPI数据表
    op.create_table('cpi_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('month', sa.String(length=10), nullable=False, comment='月份'),
        sa.Column('nt_val', sa.Numeric(precision=8, scale=4), nullable=True, comment='全国当月值'),
        sa.Column('nt_yoy', sa.Numeric(precision=8, scale=4), nullable=True, comment='全国同比'),
        sa.Column('nt_mom', sa.Numeric(precision=8, scale=4), nullable=True, comment='全国环比'),
        sa.Column('nt_accu', sa.Numeric(precision=8, scale=4), nullable=True, comment='全国累计'),
        sa.Column('town_val', sa.Numeric(precision=8, scale=4), nullable=True, comment='城市当月值'),
        sa.Column('town_yoy', sa.Numeric(precision=8, scale=4), nullable=True, comment='城市同比'),
        sa.Column('town_mom', sa.Numeric(precision=8, scale=4), nullable=True, comment='城市环比'),
        sa.Column('town_accu', sa.Numeric(precision=8, scale=4), nullable=True, comment='城市累计'),
        sa.Column('cnt_val', sa.Numeric(precision=8, scale=4), nullable=True, comment='农村当月值'),
        sa.Column('cnt_yoy', sa.Numeric(precision=8, scale=4), nullable=True, comment='农村同比'),
        sa.Column('cnt_mom', sa.Numeric(precision=8, scale=4), nullable=True, comment='农村环比'),
        sa.Column('cnt_accu', sa.Numeric(precision=8, scale=4), nullable=True, comment='农村累计'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('month'),
        comment='CPI数据表'
    )
    op.create_index('idx_cpi_data_month', 'cpi_data', ['month'])
    
    # 创建PMI数据表
    op.create_table('pmi_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('month', sa.String(length=10), nullable=False, comment='月份'),
        sa.Column('pmi', sa.Numeric(precision=8, scale=4), nullable=True, comment='PMI指数'),
        sa.Column('prod', sa.Numeric(precision=8, scale=4), nullable=True, comment='生产指数'),
        sa.Column('new_order', sa.Numeric(precision=8, scale=4), nullable=True, comment='新订单指数'),
        sa.Column('new_exp_order', sa.Numeric(precision=8, scale=4), nullable=True, comment='新出口订单指数'),
        sa.Column('order_backlog', sa.Numeric(precision=8, scale=4), nullable=True, comment='在手订单指数'),
        sa.Column('inv', sa.Numeric(precision=8, scale=4), nullable=True, comment='产成品库存指数'),
        sa.Column('purchase', sa.Numeric(precision=8, scale=4), nullable=True, comment='采购量指数'),
        sa.Column('import_index', sa.Numeric(precision=8, scale=4), nullable=True, comment='进口指数'),
        sa.Column('purchase_price', sa.Numeric(precision=8, scale=4), nullable=True, comment='主要原材料购进价格指数'),
        sa.Column('ex_factory_price', sa.Numeric(precision=8, scale=4), nullable=True, comment='出厂价格指数'),
        sa.Column('emp_index', sa.Numeric(precision=8, scale=4), nullable=True, comment='从业人员指数'),
        sa.Column('sup_del_time', sa.Numeric(precision=8, scale=4), nullable=True, comment='供应商配送时间指数'),
        sa.Column('bus_act_exp', sa.Numeric(precision=8, scale=4), nullable=True, comment='生产经营活动预期指数'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('month'),
        comment='PMI数据表'
    )
    op.create_index('idx_pmi_data_month', 'pmi_data', ['month'])
    
    # 创建货币供应量数据表
    op.create_table('money_supply_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('month', sa.String(length=10), nullable=False, comment='月份'),
        sa.Column('m0', sa.Numeric(precision=20, scale=2), nullable=True, comment='货币和准货币(M0)'),
        sa.Column('m0_yoy', sa.Numeric(precision=8, scale=4), nullable=True, comment='M0同比增长率'),
        sa.Column('m1', sa.Numeric(precision=20, scale=2), nullable=True, comment='货币(M1)'),
        sa.Column('m1_yoy', sa.Numeric(precision=8, scale=4), nullable=True, comment='M1同比增长率'),
        sa.Column('m2', sa.Numeric(precision=20, scale=2), nullable=True, comment='广义货币(M2)'),
        sa.Column('m2_yoy', sa.Numeric(precision=8, scale=4), nullable=True, comment='M2同比增长率'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('month'),
        comment='货币供应量数据表'
    )
    op.create_index('idx_money_supply_data_month', 'money_supply_data', ['month'])
    
    # 创建利率数据表
    op.create_table('interest_rate_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('date', sa.Date(), nullable=False, comment='日期'),
        sa.Column('rate_type', sa.String(length=20), nullable=False, comment='利率类型'),
        sa.Column('rate_name', sa.String(length=50), nullable=False, comment='利率名称'),
        sa.Column('rate_value', sa.Numeric(precision=8, scale=4), nullable=True, comment='利率值'),
        sa.Column('term', sa.String(length=20), nullable=True, comment='期限'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('date', 'rate_type', 'rate_name'),
        comment='利率数据表'
    )
    op.create_index('idx_interest_rate_data_date', 'interest_rate_data', ['date'])
    op.create_index('idx_interest_rate_data_rate_type', 'interest_rate_data', ['rate_type'])
    op.create_index('idx_interest_rate_data_rate_name', 'interest_rate_data', ['rate_name'])
    
    # 创建指数基础信息表
    op.create_table('index_basic_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='指数代码'),
        sa.Column('name', sa.String(length=100), nullable=False, comment='指数名称'),
        sa.Column('fullname', sa.String(length=200), nullable=True, comment='指数全称'),
        sa.Column('market', sa.String(length=20), nullable=True, comment='市场'),
        sa.Column('publisher', sa.String(length=100), nullable=True, comment='发布方'),
        sa.Column('index_type', sa.String(length=20), nullable=True, comment='指数类型'),
        sa.Column('category', sa.String(length=20), nullable=True, comment='指数分类'),
        sa.Column('base_date', sa.Date(), nullable=True, comment='基期'),
        sa.Column('base_point', sa.Numeric(precision=20, scale=4), nullable=True, comment='基点'),
        sa.Column('list_date', sa.Date(), nullable=True, comment='发布日期'),
        sa.Column('weight_rule', sa.String(length=100), nullable=True, comment='加权方式'),
        sa.Column('desc', sa.Text(), nullable=True, comment='描述'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code'),
        comment='指数基础信息表'
    )
    op.create_index('idx_index_basic_info_ts_code', 'index_basic_info', ['ts_code'])
    op.create_index('idx_index_basic_info_market', 'index_basic_info', ['market'])
    op.create_index('idx_index_basic_info_index_type', 'index_basic_info', ['index_type'])
    
    # 创建指数日线数据表
    op.create_table('index_daily_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='指数代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('close', sa.Numeric(precision=20, scale=4), nullable=True, comment='收盘点位'),
        sa.Column('open', sa.Numeric(precision=20, scale=4), nullable=True, comment='开盘点位'),
        sa.Column('high', sa.Numeric(precision=20, scale=4), nullable=True, comment='最高点位'),
        sa.Column('low', sa.Numeric(precision=20, scale=4), nullable=True, comment='最低点位'),
        sa.Column('pre_close', sa.Numeric(precision=20, scale=4), nullable=True, comment='昨收点位'),
        sa.Column('change', sa.Numeric(precision=20, scale=4), nullable=True, comment='涨跌点'),
        sa.Column('pct_chg', sa.Numeric(precision=8, scale=4), nullable=True, comment='涨跌幅'),
        sa.Column('vol', sa.Numeric(precision=20, scale=2), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=20, scale=2), nullable=True, comment='成交额'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='指数日线数据表'
    )
    op.create_index('idx_index_daily_data_ts_code', 'index_daily_data', ['ts_code'])
    op.create_index('idx_index_daily_data_trade_date', 'index_daily_data', ['trade_date'])
    op.create_index('idx_index_daily_data_ts_code_trade_date', 'index_daily_data', ['ts_code', 'trade_date'])
    
    # 创建指数权重数据表
    op.create_table('index_weight_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('index_code', sa.String(length=20), nullable=False, comment='指数代码'),
        sa.Column('con_code', sa.String(length=20), nullable=False, comment='成分股代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('weight', sa.Numeric(precision=8, scale=4), nullable=True, comment='权重'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('index_code', 'con_code', 'trade_date'),
        comment='指数权重数据表'
    )
    op.create_index('idx_index_weight_data_index_code', 'index_weight_data', ['index_code'])
    op.create_index('idx_index_weight_data_con_code', 'index_weight_data', ['con_code'])
    op.create_index('idx_index_weight_data_trade_date', 'index_weight_data', ['trade_date'])
    
    # 创建指数成分股数据表
    op.create_table('index_member_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('index_code', sa.String(length=20), nullable=False, comment='指数代码'),
        sa.Column('con_code', sa.String(length=20), nullable=False, comment='成分股代码'),
        sa.Column('con_name', sa.String(length=100), nullable=True, comment='成分股名称'),
        sa.Column('in_date', sa.Date(), nullable=True, comment='纳入日期'),
        sa.Column('out_date', sa.Date(), nullable=True, comment='剔除日期'),
        sa.Column('is_new', sa.String(length=1), nullable=True, comment='是否最新'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('index_code', 'con_code', 'in_date'),
        comment='指数成分股数据表'
    )
    op.create_index('idx_index_member_data_index_code', 'index_member_data', ['index_code'])
    op.create_index('idx_index_member_data_con_code', 'index_member_data', ['con_code'])
    op.create_index('idx_index_member_data_in_date', 'index_member_data', ['in_date'])
    
    # 创建指数月线数据表
    op.create_table('index_monthly_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('ts_code', sa.String(length=20), nullable=False, comment='指数代码'),
        sa.Column('trade_date', sa.Date(), nullable=False, comment='交易日期'),
        sa.Column('close', sa.Numeric(precision=20, scale=4), nullable=True, comment='收盘点位'),
        sa.Column('open', sa.Numeric(precision=20, scale=4), nullable=True, comment='开盘点位'),
        sa.Column('high', sa.Numeric(precision=20, scale=4), nullable=True, comment='最高点位'),
        sa.Column('low', sa.Numeric(precision=20, scale=4), nullable=True, comment='最低点位'),
        sa.Column('pre_close', sa.Numeric(precision=20, scale=4), nullable=True, comment='昨收点位'),
        sa.Column('change', sa.Numeric(precision=20, scale=4), nullable=True, comment='涨跌点'),
        sa.Column('pct_chg', sa.Numeric(precision=8, scale=4), nullable=True, comment='涨跌幅'),
        sa.Column('vol', sa.Numeric(precision=20, scale=2), nullable=True, comment='成交量'),
        sa.Column('amount', sa.Numeric(precision=20, scale=2), nullable=True, comment='成交额'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('ts_code', 'trade_date'),
        comment='指数月线数据表'
    )
    op.create_index('idx_index_monthly_data_ts_code', 'index_monthly_data', ['ts_code'])
    op.create_index('idx_index_monthly_data_trade_date', 'index_monthly_data', ['trade_date'])
    
    # 创建指数分类数据表
    op.create_table('index_classify_data',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('index_code', sa.String(length=20), nullable=False, comment='指数代码'),
        sa.Column('industry_code', sa.String(length=20), nullable=False, comment='行业代码'),
        sa.Column('industry_name', sa.String(length=100), nullable=True, comment='行业名称'),
        sa.Column('level', sa.String(length=10), nullable=True, comment='行业级别'),
        sa.Column('src', sa.String(length=20), nullable=True, comment='行业分类标准'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('index_code', 'industry_code'),
        comment='指数分类数据表'
    )
    op.create_index('idx_index_classify_data_index_code', 'index_classify_data', ['index_code'])
    op.create_index('idx_index_classify_data_industry_code', 'index_classify_data', ['industry_code'])
    op.create_index('idx_index_classify_data_level', 'index_classify_data', ['level'])
    
    # 创建新闻基础信息表
    op.create_table('news_basic_info',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('news_id', sa.String(length=50), nullable=False, comment='新闻ID'),
        sa.Column('title', sa.String(length=500), nullable=False, comment='新闻标题'),
        sa.Column('content', sa.Text(), nullable=True, comment='新闻内容'),
        sa.Column('source', sa.String(length=100), nullable=True, comment='新闻来源'),
        sa.Column('author', sa.String(length=100), nullable=True, comment='作者'),
        sa.Column('publish_time', sa.DateTime(timezone=True), nullable=True, comment='发布时间'),
        sa.Column('category', sa.String(length=50), nullable=True, comment='新闻分类'),
        sa.Column('tags', postgresql.ARRAY(sa.String(length=50)), nullable=True, comment='标签'),
        sa.Column('url', sa.String(length=500), nullable=True, comment='新闻链接'),
        sa.Column('view_count', sa.BigInteger(), nullable=True, comment='浏览量'),
        sa.Column('comment_count', sa.BigInteger(), nullable=True, comment='评论数'),
        sa.Column('like_count', sa.BigInteger(), nullable=True, comment='点赞数'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('news_id'),
        comment='新闻基础信息表'
    )
    op.create_index('idx_news_basic_info_title', 'news_basic_info', ['title'])
    op.create_index('idx_news_basic_info_source', 'news_basic_info', ['source'])
    op.create_index('idx_news_basic_info_publish_time', 'news_basic_info', ['publish_time'])
    op.create_index('idx_news_basic_info_category', 'news_basic_info', ['category'])
    
    # 创建新闻内容表
    op.create_table('news_content',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('news_id', sa.String(length=50), nullable=False, comment='新闻ID'),
        sa.Column('content_type', sa.String(length=20), nullable=False, comment='内容类型'),
        sa.Column('content_text', sa.Text(), nullable=True, comment='文本内容'),
        sa.Column('content_html', sa.Text(), nullable=True, comment='HTML内容'),
        sa.Column('summary', sa.Text(), nullable=True, comment='内容摘要'),
        sa.Column('keywords', postgresql.ARRAY(sa.String(length=100)), nullable=True, comment='关键词'),
        sa.Column('entities', postgresql.JSONB(), nullable=True, comment='实体信息'),
        sa.Column('word_count', sa.Integer(), nullable=True, comment='字数'),
        sa.Column('reading_time', sa.Integer(), nullable=True, comment='阅读时间(分钟)'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('news_id', 'content_type'),
        comment='新闻内容表'
    )
    op.create_index('idx_news_content_news_id', 'news_content', ['news_id'])
    op.create_index('idx_news_content_content_type', 'news_content', ['content_type'])
    
    # 创建新闻热门话题表
    op.create_table('news_hot_topics',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('topic_id', sa.String(length=50), nullable=False, comment='话题ID'),
        sa.Column('topic_name', sa.String(length=200), nullable=False, comment='话题名称'),
        sa.Column('topic_description', sa.Text(), nullable=True, comment='话题描述'),
        sa.Column('category', sa.String(length=50), nullable=True, comment='话题分类'),
        sa.Column('heat_score', sa.Numeric(precision=10, scale=2), nullable=True, comment='热度分数'),
        sa.Column('news_count', sa.Integer(), nullable=True, comment='相关新闻数量'),
        sa.Column('start_time', sa.DateTime(timezone=True), nullable=True, comment='话题开始时间'),
        sa.Column('peak_time', sa.DateTime(timezone=True), nullable=True, comment='话题高峰时间'),
        sa.Column('end_time', sa.DateTime(timezone=True), nullable=True, comment='话题结束时间'),
        sa.Column('related_stocks', postgresql.ARRAY(sa.String(length=20)), nullable=True, comment='相关股票代码'),
        sa.Column('keywords', postgresql.ARRAY(sa.String(length=100)), nullable=True, comment='关键词'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('topic_id'),
        comment='新闻热门话题表'
    )
    op.create_index('idx_news_hot_topics_topic_name', 'news_hot_topics', ['topic_name'])
    op.create_index('idx_news_hot_topics_category', 'news_hot_topics', ['category'])
    op.create_index('idx_news_hot_topics_heat_score', 'news_hot_topics', ['heat_score'])
    op.create_index('idx_news_hot_topics_peak_time', 'news_hot_topics', ['peak_time'])
    
    # 创建新闻情感分析表
    op.create_table('news_sentiment_analysis',
        sa.Column('id', sa.BigInteger(), nullable=False),
        sa.Column('news_id', sa.String(length=50), nullable=False, comment='新闻ID'),
        sa.Column('sentiment_score', sa.Numeric(precision=8, scale=4), nullable=True, comment='情感分数'),
        sa.Column('sentiment_label', sa.String(length=20), nullable=True, comment='情感标签'),
        sa.Column('positive_score', sa.Numeric(precision=8, scale=4), nullable=True, comment='正面情感分数'),
        sa.Column('negative_score', sa.Numeric(precision=8, scale=4), nullable=True, comment='负面情感分数'),
        sa.Column('neutral_score', sa.Numeric(precision=8, scale=4), nullable=True, comment='中性情感分数'),
        sa.Column('confidence', sa.Numeric(precision=8, scale=4), nullable=True, comment='置信度'),
        sa.Column('analysis_model', sa.String(length=50), nullable=True, comment='分析模型'),
        sa.Column('analysis_time', sa.DateTime(timezone=True), nullable=True, comment='分析时间'),
        sa.Column('market_impact', sa.String(length=20), nullable=True, comment='市场影响'),
        sa.Column('related_stocks', postgresql.ARRAY(sa.String(length=20)), nullable=True, comment='相关股票代码'),
        sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
        sa.Column('version', sa.Integer(), nullable=False, server_default='1'),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('news_id'),
        comment='新闻情感分析表'
    )
    op.create_index('idx_news_sentiment_analysis_news_id', 'news_sentiment_analysis', ['news_id'])
    op.create_index('idx_news_sentiment_analysis_sentiment_label', 'news_sentiment_analysis', ['sentiment_label'])
    op.create_index('idx_news_sentiment_analysis_sentiment_score', 'news_sentiment_analysis', ['sentiment_score'])
    op.create_index('idx_news_sentiment_analysis_analysis_time', 'news_sentiment_analysis', ['analysis_time'])


def downgrade() -> None:
    """降级数据库架构"""
    
    # 删除新闻相关表
    op.drop_table('news_sentiment_analysis')
    op.drop_table('news_hot_topics')
    op.drop_table('news_content')
    op.drop_table('news_basic_info')
    
    # 删除指数相关表
    op.drop_table('index_classify_data')
    op.drop_table('index_monthly_data')
    op.drop_table('index_member_data')
    op.drop_table('index_weight_data')
    op.drop_table('index_daily_data')
    op.drop_table('index_basic_info')
    
    # 删除宏观经济相关表
    op.drop_table('interest_rate_data')
    op.drop_table('money_supply_data')
    op.drop_table('pmi_data')
    op.drop_table('cpi_data')
    op.drop_table('gdp_data')
    op.drop_table('macro_economic_data')
    
    # 删除期权相关表
    op.drop_table('options_minute_data')
    op.drop_table('options_position_analysis')
    op.drop_table('options_greeks_data')
    op.drop_table('options_daily_data')
    op.drop_table('options_basic_info')
    
    # 删除期货相关表
    op.drop_table('futures_minute_data')
    op.drop_table('futures_main_contract')
    op.drop_table('futures_warehouse_data')
    op.drop_table('futures_holding_data')
    op.drop_table('futures_daily_data')
    op.drop_table('futures_basic_info')
    
    # 删除基金相关表
    op.drop_table('fund_share_data')
    op.drop_table('fund_dividend_data')
    op.drop_table('fund_manager_info')
    op.drop_table('fund_portfolio_data')
    op.drop_table('fund_nav_data')
    op.drop_table('fund_basic_info')
    
    # 删除债券相关表
    op.drop_table('bond_issuer_info')
    op.drop_table('bond_rating_data')
    op.drop_table('bond_yield_data')
    op.drop_table('bond_daily_data')
    op.drop_table('bond_basic_info')
    
    # 删除股票相关表
    op.drop_table('stock_dividend_info')
    op.drop_table('stock_holder_info')
    op.drop_table('stock_money_flow')
    op.drop_table('stock_technical_indicators')
    op.drop_table('stock_financial_data')
    op.drop_table('stock_minute_data')
    op.drop_table('stock_daily_data')
    op.drop_table('stock_basic_info')